#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <unistd.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sqlite3.h>

#include "../include/server.h"

#define CRC16_ITU_T_POLY 0x1021   /* Define the CRC-ITU-T polynomial */

int                listen_port = 0;

//sqlite
char               *sqlite_filename = "../sqlite/server_sqlite.db";
char               *table_name = "sampling_data";
sqlite3            *db = NULL;
char               sql[128] = {0};

static uint16_t crc_itu_t(const uint8_t *data, size_t length)
{
    uint16_t          crc = 0xFFFF;
    size_t            i, j;

    for (i=0; i<length; i++)
    {
        crc ^= ((uint16_t)data[i] << 8);

        for(j=0; j<8; j++)
        {
            if (crc & 0x8000)
            {
                crc = (crc << 1) ^ CRC16_ITU_T_POLY;
            }
            else
            {
                crc <<= 1;
            }
        }
    }

    return crc;
}

int main(int argc, char **argv)
{

	char				temperature[16] = {0};
	uint8_t				time[16] = {0};
	char				strtime[32] = {0};
	char				device[16] = {0};
	uint16_t			crc;
	char                buf[BUFSIZE] = {0};
	int                 i = 0;
	int                 rv = 0;
	/********socket初始化模块用到的变量*********/
	struct sockaddr_in  server_addr;
	struct sockaddr_in  client_addr;
	int                 listen_fd = -1;
	int                 client_fd = -1;
	socklen_t           addrlen = sizeof(client_addr);


	/************select模块用到的变量***********/
	int                 fd_array[FD_NUM] = {0};
	fd_set              rdset;
	int                 maxfd = -1;

	/**********************************获取参数模块****************************************/
	server_getopt_long(argc, argv);

	//create table
	memset(sql, 0, sizeof(sql));
	snprintf(sql, sizeof(sql), "create table %s(data text);", table_name, buf);
	sqlite(sqlite_filename, db, sql, NULL);

	/**********************************socket初始化模块***********************************/
	listen_fd = socket_server_init(NULL, listen_port);
	//printf("socket server init succssfully:[listen port:%d, listen fd:%d]\n", listen_port, listen_fd);
	if(listen_fd < 0)
	{
		printf("server socket init failure:%s\n", strerror(errno));
		return -1;
	}

	/*************初始化fd_array数组********/
	for(i=0; i<FD_NUM; i++)
	{
		fd_array[i] = -1;
	}
	fd_array[0] = listen_fd;

	/**********************************select监听事件模块*********************************/
	while(1)
	{
		/******************更新rdset、maxfd**********************/
		FD_ZERO(&rdset);
		for(i=0; i<FD_NUM; i++)
		{
			if(fd_array[i]<0) continue;
			FD_SET(fd_array[i], &rdset);
			maxfd = (fd_array[i] > maxfd ? fd_array[i] : maxfd);
		}

		/***********************select*************************/
		printf("\nstart listen thing coming...\n");
		rv = select(maxfd+1, &rdset, NULL, NULL, NULL);
		if(rv < 0)
		{
			printf("select failure:%s\n",strerror(errno));
			continue;
		}
		else if(rv == 0)
		{
			printf("select timeout\n");
			continue;
		}

		/****************判断发生事件类型*********************/
		if(FD_ISSET(listen_fd,&rdset))//新客户端连接
		{
			int fd_array_full = 1;//已连接的客户端爆满标志，1为爆满，0为未满

			client_fd = accept(listen_fd, (struct sockaddr *)&client_addr, &addrlen);
			if(client_fd < 0)
			{
				printf("accept failure:%s\n",strerror(errno));
				continue;
			}
			printf("accept new client[%d]:[ip:%s|port:%d]\n",
					client_fd, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

			for(i=1; i<FD_NUM; i++)//添加该客户端到fd_array中
			{
				if(fd_array[i] > 0) continue;
				fd_array[i] = client_fd;
				fd_array_full = 0;
				break;
			}

			if(fd_array_full)
            {
				printf("fd_array full!");
                close(client_fd);
                continue;
            }

		}
		else//客户端发生事件
		{
			for(i=0; i<FD_NUM; i++)//遍历所有客户端，找到发生事件的客户端为止
			{
				if(fd_array[i] < 0 || !FD_ISSET(fd_array[i], &rdset))
					continue;

				memset(buf, 0, sizeof(buf));
				rv = read(fd_array[i], buf, sizeof(buf));
				if(rv < 0)
				{
					printf("read data failure:%s\n", strerror(errno));
					break;
				}
				else if(rv == 0)//连接断开
				{
					printf(" client[%d] disconnect,remove it's fd out of fd_array\n",fd_array[i]);
					close(fd_array[i]);
					fd_array[i] = -1;
					break;
				}
				else//数据到来
				{
					//crc = crc_itu_t(buf, strlen(buf));
					if(buf[0]==0xFE && buf[1]==0xED )
					{
						//for(i=0; i<23; i++)
						//{
						//	printf("buf[%d]:0x%02X ", i, buf[i]);
						//}
						printf("\nget TLV data\n");
						if(buf[2] == 1)//temperature
						{
							printf("get data is sampling temperature\n");
							
							for(i=5; i<5+8; i++)
							{
								device[i-5] = buf[i];
							}
							printf("device:%s, length:%d\n", device, strlen(device));

							for(i=13; i<13+6; i++)
							{
								time[i-13] = (uint8_t)buf[i];
							}
							snprintf(strtime, sizeof(strtime), "%04d-%02d-%02d %02d:%02d:%02d", 
									time[0]+2000, time[1], time[2], time[3], time[4], time[5]);
							printf("time:%s\n", strtime);

							snprintf(temperature, sizeof(temperature), "%02d.%02d", 
									(uint8_t)buf[19], (uint8_t)buf[20]);
							printf("temperature:%s\n", temperature);

							printf("CRC:%02X%02X\n", (uint8_t)buf[21], (uint8_t)buf[22]);

						}
						if(buf[2] == 2)//湿度
						{}
						if(buf[2] == 3)//noisy
						{}

						/*****将数据存入sqlite数据库模块*******/
						memset(sql, 0, sizeof(sql));
						snprintf(sql, sizeof(sql), "insert into %s values('%s|%s|%s');", 
								table_name, device, strtime, temperature);
						sqlite(sqlite_filename, db, sql, NULL);


					}
					else
					{
						printf("read data %d bytes from client[%d]:%s\n",rv, fd_array[i], buf);

						/*****将数据存入sqlite数据库模块*******/
						memset(sql, 0, sizeof(sql));
						snprintf(sql, sizeof(sql), "insert into %s values('%s');", table_name, buf);
						sqlite(sqlite_filename, db, sql, NULL);
					}
				}
			}
		}
	}

	for(i=0; i<FD_NUM; i++)
	{
		if(fd_array[i] < 0) continue;
		close(fd_array[i]);
	}
	return 0;
}

